# encoding: utf-8
# This controller was added by william
class TagsController < ApplicationController
  layout "base_tags"

  before_filter :require_admin, :only => :show

  include ProjectsHelper
  include ActsAsTaggableOn::TagsHelper
  helper :projects
  include TagsHelper
  helper :tags
  include OpenSourceProjectsHelper
  include RelativeMemosHelper

  before_filter :require_admin, :only => [:delete, :show_all]

  # $selected_tags = Array.new
  # $related_tags = Array.new
  NUMBERS = Setting.tags_show_search_results

  # 预设几个可以添加的tag
  #@preTags = %w|预设A 预设B 预设C 预设D 预设E 预设F |

  # 接收参数解释：
  # params[:q]这是在其他页面点击tag，跳转到该页面后的结果显示 ;params[:selected_tags]，这是在过滤页面增删tag进行过滤传过来的参数
  # 最后是2个过滤何种数据，显示结果的控制参数params[:obj_id],params[:object_falg]
  # 0代表删除tag 1代表增加tag
  def index

    @obj_id = params[:obj_id]
    @obj_flag = params[:object_flag]

    @selected_tags = Array.new
    @related_tags = nil

    if params[:q]
      @selected_tags << params[:q]
    else
      @do_what = params[:do_what]
      @tag = params[:tag]
      @selected_tags = params[:current_selected_tags]
      @selected_tags = @selected_tags.nil? ? Array.new : @selected_tags

      case @do_what
        when '0' then
          @selected_tags.delete @tag #数组中删除有多方式 可以改用shift,pop
        when '1' then
          # 判断是否已存在该tag 主要用来处理分页的情况
          unless @selected_tags.include? @tag
            @selected_tags << @tag
          end
      end
    end

    #gcm 效率低，暂时移除
    #@users_tags_num,@projects_tags_num,@issues_tags_num,@bids_tags_num,@contests_tags_num,
    #@forum_tags_num, @attachments_tags_num, @open_source_projects_num = get_tags_size

    # 获取搜索结果 
    @obj, @obj_pages, @results_count, @users_results,
        @projects_results,
        @issues_results,
        @bids_results,
        @forums_results,
        @attachments_results,
        @contests_tags,
        @open_source_projects_results,
        @topics_results = refresh_results(@obj_id, @obj_flag, @selected_tags)

    # 这里是做tag推荐用的， 用来生产推荐的tags
    unless @obj.nil?
      @tags = @obj.tag_list
      @tags -= @selected_tags
      # @selected_tags.each do |i|
      #   @tags.delete(i)
      # end    
      @related_tags = @tags
    else
      return
    end

  end

  # 增加已选的tag
  def add_tag
    @tag = params[:tag]
    @show_flag = params[:show_flag]

    $selected_tags << @tag
    $related_tags.delete(@tag)

    # 获取搜索结果 
    @obj, @obj_pages, @results_count, @users_results,
        @projects_results,
        @issues_results,
        @bids_results,
        @forums_results,
        @attachments_results,
        @contests_results = refresh_results(@obj_id, @show_flag)
  end

  # 删除已选tag 
  def delete_tag
    @tag = params[:tag]
    @show_flag = params[:show_flag]

    $related_tags << @tag
    $selected_tags.delete(@tag)

    # 获取搜索结果 
    @obj, @obj_pages, @results_count, @users_results,
        @projects_results,
        @issues_results,
        @bids_results,
        @forums_results,
        @attachments_results,
        @contests_results = refresh_results(@obj_id, @show_flag)
  end

  def show_all
    @tags = ActsAsTaggableOn::Tag.find(:all)
  end

  # 完全从数据库删除tag
  # 这种删除方式是针对 印有该 tag所有对象来做删除的
  # 这样是从整个系统数据库中把该tag删除了
  def delete
    if params[:q]
      @tag = ActsAsTaggableOn::Tag.find_by_id(params[:q])
      @tag.delete
      @taggings = ActsAsTaggableOn::Tagging.find_all_by_tag_id(@tag.id)
      @taggings.each do |tagging|
        tagging.delete
      end
    end
  end

  # 只删除某个对象的该tag
  def remove_tag
    @obj = nil
    @object_flag = nil

    if request.get?
      # 获取传过来的tag_id taggable_id 和  taggable_type,通过2者确定要删除tag的对象
      @tag_name = params[:tag_name]
      @tag_id = (ActsAsTaggableOn::Tag.find_by_name(@tag_name)).id
      @taggable_id = params[:taggable_id] # 当做参数传时对象会变成字符串
      @taggable_type = numbers_to_object_type(params[:taggable_type])

      @obj = get_object(@taggable_id, params[:taggable_type])
      @object_flag = params[:taggable_type]

      # if can_remove_tag?(User.current,@taggable_id,@taggable_type)

      @taggings = ActsAsTaggableOn::Tagging.find_by_tag_id_and_taggable_id_and_taggable_type(@tag_id, @taggable_id, @taggable_type)

      unless @taggings.nil?
        @taggings.delete
      end

      # 是否还有其他记录 引用了 tag_id
      @tagging = ActsAsTaggableOn::Tagging.find_by_tag_id(@tag_id)
      # 如果taggings表中记录已经不存在 ，那么检查tags表 作删除动作
      if @tagging.nil?
        @tag = ActsAsTaggableOn::Tag.find_by_id(@tag_id)
        @tag.delete unless @tag.nil?
      end
      # end
    end
  end
  
  private
  # 这里用来刷新搜索结果的区域
  # 函数的返回值 前2字段用来处理获取其他tag和分页 ，另外4个返回值为过滤结果
  def refresh_results(obj_id, obj_flag, selected_tags)
    @users_results = nil
    @projects_results = nil
    @issues_results = nil
    @bids_results = nil
    @contests_results = nil
    @forums_results = nil
    attachments_results = nil
    @open_source_projects_results = nil
    @obj_pages = nil
    @obj = nil
    @result = nil
    @topics_results = nil

    # 这里为了提高系统的响应速度 把搜索结果放到case中去了
    case obj_flag
      when '1' then
        @obj = User.find_by_id(obj_id)
        @obj_pages, @users_results, @results_count = for_pagination(get_users_by_tag(selected_tags))
      when '2' then
        @obj = Project.find_by_id(obj_id)
        @obj_pages, @projects_results, @results_count = for_pagination(get_projects_by_tag(selected_tags))
      when '3' then
        @obj = Issue.find_by_id(obj_id)
        @obj_pages, @issues_results, @results_count = for_pagination(get_issues_by_tag(selected_tags))
      when '4' then
        @obj_pages, @bids_results, @results_count = for_pagination(get_bids_by_tag(selected_tags))
        @obj = Bid.find_by_id(obj_id)
      when '5'
        @obj = Forum.find_by_id(obj_id)
        @obj_pages, @forums_results, @results_count = for_pagination(get_forums_by_tag(selected_tags))
      when '6'
        @obj = Attachment.find_by_id(obj_id)

        # modifed by Long Jun
        # this is used to find the attachments that came from the same project and tagged with the same tag.
        @result = get_attachments_by_project_tag(selected_tags, @obj)
        @obj_pages, attachments_results, @results_count = for_pagination(@result)
      when '7'
        @obj = Contest.find_by_id(obj_id)
        @obj_pages, @contests_results, @results_count = for_pagination(get_contests_by_tag(selected_tags))
      when '8'
        @obj = OpenSourceProject.find_by_id(obj_id)
        @obj_pages, @open_source_projects_results, @results_count = for_pagination(get_open_source_projects_by_tag(selected_tags))
      when '9'
        @obj = RelativeMemo.find_by_id(obj_id)
        @obj_pages, @topics_results, @results_count = for_pagination(get_topics_by_tag(selected_tags))
      else
        @obj = nil
    end
    return [@obj,
            @obj_pages,
            @results_count,
            @users_results,
            @projects_results,
            @issues_results,
            @bids_results,
            @forums_results,
            attachments_results,
            @contests_results,
            @open_source_projects_results,
            @topics_results]
  end

  def for_pagination(results)
    @offset, @limit = api_offset_and_limit({:limit => NUMBERS}) # 设置每页显示的个数
    @results_count = results.count
    @obj_pages = Paginator.new @results_count, @limit, params['page'] # 3个参数分别是：总数，每页显示数目，第几页
    @offset ||= @obj_pages.offset
    results = results.offset(@offset).limit(@limit).all # 这里默认设置为按时间排序
    return @obj_pages, results, @results_count
  end

  # 获取有某类对象的tag总数
  def get_tags_size
    @issues_tags_num = Issue.tag_counts.size
    @projects_tags_num = Project.tag_counts.size
    @users_tags_num = User.tag_counts.size
    @bids_tags_num = Bid.tag_counts.size
    forum_tags_num = Forum.tag_counts.size
    attachment_tags_num = Attachment.tag_counts.size
    @open_source_projects_num = OpenSourceProject.tag_counts.size
    @contests_tags_num = Contest.tag_counts.size
    return @users_tags_num, @projects_tags_num, @issues_tags_num, @bids_tags_num, forum_tags_num, attachment_tags_num, @contests_tags_num, @open_source_projects_num
  end

  # 通过数字 来转换出对象的类型 
  # 1代表是user类型   2代表是project类型  3代表是issue类型   4代表需求
  # 这个函数 重构是可以移动到application_helper中去 
  # 当做一个全局的函数使用，有好几个地方使用到了
  def numbers_to_object_type(num)
    case num
      when '1'
        return 'Principal'
      when '2'
        return 'Project'
      when '3'
        return 'Issue'
      when '4'
        return 'Bid'
      when '5'
        return 'Forum'
      when '6'
        return 'Attachment'
      when '7'
        return 'Contest'
      when '8'
        return 'OpenSourceProject'
      else
        render_error :message => e.message
        return
    end
  end

end
